﻿namespace NetFx.SMIL.Definitions
{
  using System;
  using System.Text;
  using System.Collections;
  using System.Collections.Generic;

  using System.Reflection;
  using System.Reflection.Emit;
  using System.Runtime.InteropServices;

  using System.Diagnostics;
  using System.Diagnostics.CodeAnalysis;
  using System.Diagnostics.SymbolStore;
  using System.Security;
  using System.Security.Permissions;

  using NetFx.MSIL;
  using NetFx.SMIL;
  using NetFx.SMIL.References;


  /// <summary>
  /// 定义。
  /// </summary>
  public abstract class ReflectDef:IDisposable
  {
    #region Statics
    /// <summary>
    /// 定义ReflectDef.
    /// </summary>
    public static ReflectDef Define(string name,DefType type)
    {
      switch (type)
      {
        case DefType.Assembly:
          return AssemblyDef.of(name);
        case DefType.Enum:
          return EnumDef.of(name);
        case DefType.Event:
          return EventDef.of(name);
        case DefType.Field:
          return FieldDef.of(name);
        case DefType.Label:
          return LabelDef.of(name);
        case DefType.Method:
          return MethodDef.of(name);
        case DefType.Module:
          return ModuleDef.of(name);
        case DefType.Parameter:
          return ParameterDef.of(name);
        case DefType.Property:
          return PropertyDef.of(name);
        case DefType.Type:
          return TypeDef.of(name);
        case DefType.Variable:
          return VariableDef.of(name);
        default:
          return null; 
      }
    }
    /// <summary>
    /// 创建反射定义。
    /// </summary>
    /// <param name="name">名称（仅对source为Label和Variable有效）</param>
    /// <param name="source">源。</param>
    /// <returns>对应的反射定义。</returns>
    public static ReflectDef of(string name, object source)
    {
      if (source != null)
      {
        if (source is Assembly)
        {
          return AssemblyDef.of(source as Assembly);
        }
        else if (source is MemberInfo)
        {
          return MemberDef.of(source as MemberInfo);
        }
        else if (source is Label)
        {
          return LabelDef.of(name, (Label)source);
        }
        else if (source is Module)
        {
          return ModuleDef.of(source as Module);
        }
        else if (source is ParameterInfo)
        {
          return ParameterDef.of(source as ParameterInfo);
        }
        else if (source is LocalVariableInfo)
        {
          return VariableDef.of(name, source as LocalVariableInfo);
        }
      }
      return null;
    }
    #endregion
    #region Consts
    public const BindingFlags AllAccessFlags = 
      BindingFlags.Public | 
      BindingFlags.NonPublic | 
      BindingFlags.Static | 
      BindingFlags.Instance;
    #endregion
    #region Fields
    /// <summary>
    /// 定义的名称。
    /// </summary>
    protected string name = string.Empty;
    /// <summary>
    /// 记录定义是否被处置。
    /// </summary>
    protected bool isDisposed = false;
    /// <summary>
    /// 记录是否使用using语法实现块的定义。
    /// </summary>
    protected bool? usingSyntax = false;
    /// <summary>
    /// 当前定义的父层定义，如果存在的话。
    /// </summary>
    protected ReflectDef parent = null;
    #endregion
    #region Properties
    /// <summary>
    /// 获取定义的类型。
    /// </summary>
    public virtual DefType DefinitionType
    {
      get
      {
        return DefType.Any;
      }
    }
    /// <summary>
    /// 获取或者设定定义的名称。
    /// </summary>
    public virtual string Name
    {
      get
      {
        return this.name!=null ? this.name: string.Empty;
      }
      set
      {
        this.name = value;
      }
    }
    /// <summary>
    /// 判别当前定义是否已经被处置。
    /// </summary>
    public virtual bool IsDisposed
    {
      get
      {
        return this.isDisposed;
      }
    }
    /// <summary>
    /// 获取或设置当前定义的父定义。
    /// </summary>
    public virtual ReflectDef Parent
    {
      get
      {
        return this.parent;
      }
      set
      {
        this.parent = value;
      }
    }
    /// <summary>
    /// 判别当前定义是否具有父定义。
    /// </summary>
    public virtual bool HasParent
    {
      get
      {
        return this.parent != null;
      }
    }
    /// <summary>
    /// 判断是否使用Using语法。
    /// </summary>
    public virtual bool? UsingSyntax
    {
      get
      {
        return this.usingSyntax.HasValue ? 
          this.usingSyntax:
          (
          this.HasParent ?
          this.Parent.UsingSyntax :
          false
          );
      }
      set
      {
        this.usingSyntax = value;
      }
    }
    #endregion
    #region Constructors
    public ReflectDef() : this(String.Empty) { }
    public ReflectDef(string name)
    {
      this.Name = name;
    }
    ~ReflectDef()
    {
      //此处和语法无关.
      this.Dispose(true);
    }
    #endregion
    #region Methods
    #region Publics
    public virtual AnyGenerator Generate(AnyGenerator container)
    {
      return this.IsDisposed? null: this.OnCompleting(this.OnDefining(container));
    }
    public virtual ReflectDef Reflect(object source)
    {
      return this.IsDisposed? null: this.OnReflecting(source);
    }
    public virtual void BreakReference()
    {
      if (!this.IsDisposed)
      {
        this.OnBreakingReference();
      }
    }
    public virtual void Dispose()
    {
      //有时使用using只是为了其语法,并不意味着
      //释放资源.
      this.Dispose(!this.IsDisposed && !(this.UsingSyntax.Value));
    }
    #endregion
    #region Inner impls
    protected virtual void Dispose(bool disposing)
    {
      if (disposing)
      {
        this.DisposeList(this.isDisposed = true);
      }
    }
    protected virtual void DisposeList(bool disposing)
    {

    }
    protected virtual void DisposeList(IList defs)
    {
      if (defs != null)
      {

        foreach (object def in defs)
        {
          ReflectDef rdef = def as ReflectDef;

          if (rdef != null && !rdef.IsDisposed)
          {
            rdef.Dispose();
          }
        }
        defs.Clear();
      }
    }

    protected virtual void GenerateList(AnyGenerator g,IList defs)
    {
      if (g != null && defs != null)
      {
        foreach (object def in defs)
        {
          ReflectDef rdef = def as ReflectDef;

          if (rdef != null)
          {
            rdef.Generate(g);
          }
        }
      }
    }

    protected virtual void Break(object def)
    {
      if (def != null)
      {
        if (def is ReflectDef)
        {
          (def as ReflectDef).BreakReference();
        }
        else if (def is ReflectRef)
        {
          (def as ReflectRef).Break();
        }
        else if (def is IList)
        {
          BreakList(def as IList);
        }
      }
    }
    protected virtual void BreakList(IList defs)
    {
      if (defs != null)
      {
        foreach (object def in defs)
        {
          this.Break(def);
        }
      }
    }
    protected virtual AnyGenerator OnDefining(AnyGenerator container)
    {
      return container;
    }
    protected virtual AnyGenerator OnCompleting(AnyGenerator generator)
    {
      if (generator != null)
      {
        //TODO:此操作可能引起严重的性能损失。
        //this.OnReflecting(generator.AnyBuilder);
      }
      return generator;
    }
    protected virtual ReflectDef OnReflecting(object source)
    {
      return this;
    }
    protected virtual void OnBreakingReference()
    {

    }

    protected virtual string OnNamingInstance(string typeName)
    {
      if (!string.IsNullOrEmpty(typeName))
      {
        char[] typeChars = typeName.ToCharArray();

        if (char.IsUpper(typeChars[0]))
        {
          typeChars[0] = char.ToLower(typeChars[0]);

          return new string(typeChars);
        }
      }
      return string.Empty;
    }
    protected virtual void ReloadMembers(MemberInfo[] members, IList memberRefs)
    {
      if (memberRefs != null && members != null)
      {
        memberRefs.Clear();
        foreach (MemberInfo member in members)
        {
          memberRefs.Add(MemberRef.of(member));
        }
      }
    }

    #endregion
    #endregion
  }
}
